package com.startit.csv;

import java.util.*;

import com.startit.csv.exception.ValidationException;
import com.startit.validation.IValidation;
import com.startit.validation.Validatable;
import com.startit.validation.ValidationFactory;

public class CSVField implements Validatable, Comparable {
	public enum DataType {
		STRING, INT, FLOAT, DATE;
	}

	public enum ValidationType {
		REQUIRED, MAXLENGTH, MIN, MAX, MATCH;
	}

	private String name;
	private int length;
	private int order;
	private List<IValidation> validations = new LinkedList<IValidation>();
	private String value;
	private DataType dataType = DataType.STRING;
	private Class argClass = String.class;
	private String dataFormatPattern = "yyyy-MM-dd HH:mm:ss";
	
	private ValidationFactory validationFactory = new ValidationFactory();

	public CSVField(String name) {
		super();
		this.name = name;
	}

	public CSVField(String name, int length) {
		this(name);
		this.length = length;
	}
	
	public CSVField(String name, DataType dataType) {
		this(name);
		this.setDataType(dataType);
		this.setArgClass(dataType);
	}
	
	public CSVField(String name, Class dataType) {
		this(name);
		if ("java.lang.String".equals(dataType.getName())) {
			this.setDataType(DataType.STRING);
			this.setArgClass(DataType.STRING);
		}
		if ("java.lang.Integer".equals(dataType.getName()) || "int".equals(dataType.getName())) {
			this.setDataType(DataType.INT);
			this.setArgClass(DataType.INT);
		}
		if ("java.lang.Float".equals(dataType.getName()) || "float".equals(dataType.getName())) {
			this.setDataType(DataType.FLOAT);
			this.setArgClass(DataType.FLOAT);
		}
		if ("java.util.Date".equals(dataType.getName())) {
			this.setDataType(DataType.DATE);
			this.setArgClass(DataType.DATE);
		}
	}

	public void addValidation(ValidationType type, Object param) {
		try {
			this.validations.add(validationFactory.getValidation(type, param));
		} catch (ClassCastException e) {
			throw new RuntimeException("Wrong param: " + e.getMessage(), e);
		}
	}

	/**
	 * Check if the field's value is valid
	 */
	public boolean valid() {
		for (IValidation validation:validations){
			if (validation.valid(value))
				continue;
			else 
				return false;
		}
		return true;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getLength() {
		return length;
	}

	public void setLength(int length) {
		this.length = length;
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) throws ValidationException {
		this.value = value;
		if (!valid())
			throw new ValidationException("Value: "+value+", is invalid.");
	}

	public DataType getDataType() {
		return dataType;
	}

	public void setDataType(DataType dataType) {
		this.dataType = dataType;
	}

	public Class getArgClass() {
		return argClass;
	}

	public void setArgClass(DataType dataType) {
		switch (dataType) {
		case INT:
			argClass = Integer.class;
			break;
		case FLOAT:
			argClass = Float.class;
			break;
		case DATE:
			argClass = Date.class;
			break;
		default:
			argClass = String.class;
		}
	}

	public String getDataFormatPattern() {
		return dataFormatPattern;
	}

	public void setDataFormatPattern(String dataFormatPattern) {
		this.dataFormatPattern = dataFormatPattern;
	}

	public int getOrder() {
		return order;
	}

	public void setOrder(int order) {
		this.order = order;
	}

	public int compareTo(Object obj) {
		if (!(obj instanceof CSVField))
			throw new ClassCastException();
		CSVField c = (CSVField)obj;
		return (new Integer(this.order)).compareTo(c.getOrder());
	}

}
